浏览器功能定制1:将网页内容保存为 Markdown
通过前段时间阅读 qutebrowser 代码,有了一些初步了解,开始尝试进行二次开发,实现自己喜欢的功能。
网页归档功能对我而言尤为重要。目前市面上存在许多优秀工具,比如 singlefile、scrapbook 等。包括浏览器自己也具备 MHTML 保存归档功能。
这些工具的好处,可以将网页按原貌保存。有的还提供裁剪功能,像剪报一样,裁剪自己喜欢的部分。(可能很多年轻人已经不知道什么是剪报了)
在本文中,我想更进一步,直接将网页保存为 Markdown,存入 0.0 Obsidian 介绍 中。舍弃掉样式,这是我更加希望的。
在本文中,我将记录探索过程,以及基于 qutebrowser 定制的过程。但是我没有计划开源,原因是我所基于的环境过于特殊,不具备易用性。本文可以提供一些思路,供浏览器插件开发者、Geeks 参考,相当于抛砖引玉。
调研:Html 转 Markdown
html2text
Convert HTML to Markdown-formatted text. 这个库已经 11 年没有更新了。
GitHub 首页:aaronsw/html2text: Convert HTML to Markdown-formatted text. (github.com)
Obsidian Importer
这是 Obsidian 官方的笔记导入插件,方便用户从其它笔记系统迁入 Obsidian,其中就包含 HTML 导入支持。
具体 HTML 导入代码位于这里。核心一步 htmlToMarkdown 是调用 Obsidian 的 API (在帖子中,提到具体是基于 turndown 实现的)完成。
turndown
看起来是 Obsidian htmlToMarkdown 的底层实现库,有 7.4k star,功能更加强大与完善,是一个 JavaScript 库。
由于我是用 Python 生态,Python 下要是有类似库就好了。
GitHub 首页:mixmark-io/turndown: 🛏 An HTML to Markdown converter written in JavaScript (github.com)
《将turndown项目改造成CLI版本秒杀Python版的html2text | 阿甘博客 (sharpgan.com)》这篇文章,从题目中即可了解到,turndown 比 html2text 要强大得多。
python-markdownify
《How to Convert HTML to Markdown in Python (brianli.com)》一文中提到的库。
这个库使用起来比较简单,好在扩展性也比较强大,比较容易定制。
GitHub 首页:matthewwithanm/python-markdownify: Convert HTML to Markdown (github.com)
调研:网页正文提取
GNE
GitHub 3.2k star
项目中提出一种基于可视化区域提高识别准确度,先执行一段 JavaScript 脚本,将每个元素的坐标存在标签内,然后根据坐标识别是否是网页正文。
GitHub 首页:GeneralNewsExtractor/GeneralNewsExtractor: 新闻网页正文通用抽取器 Beta 版.
文档:GNE: 通用新闻网站正文抽取器 — GeneralNewsExtractor 0.0.6 文档
newspaper
GitHub 13.2k star,有3、4年没有维护了。
News, full-text, and article metadata extraction in Python 3. Advanced docs:
GitHub 首页:codelucas/newspaper: News, full-text, and article metadata extraction in Python 3. Advanced docs:
文档:Newspaper3k: Article scraping & curation — newspaper 0.0.2 documentation
Python-Goose
3.9k star,有快10年没有维护了。
GitHub 首页:Python-Goose
goose3
A Python 3 compatible version of goose http://goose3.readthedocs.io/en/latest/index.html
仍在活跃维护中,star 715。
A Python 3 compatible version of goose http://goose3.readthedocs.io/en/latest/index.html
介绍文章《爬虫万金油,一鹅在手,抓遍全球:goose 简介 - 知乎》
html-extractor
《基于行块分布函数的通用网页正文抽取算法》的代码实现改进。
cnyangkui/html-extractor: 基于行块分布函数的通用网页正文抽取算法优化,Python实现
python-boilerpipe
python-readability
实现思路
通过 qutebrowser 命令触发,比如 save-markdown
。
网页正文提取
在《浏览器功能定制2:显示网页正文的阅读模式》中,我已经实现了一个简版的网页正文提取功能,并实现了一种简版阅读模式,通过 main-content
命令触发。
我准备按照如下工作流:打开网页,main-content
提取正文 HTML、save-markdown
进行保存。中间两个命令采用手动触发的方式。
Obsidian 目录创建
接下来开始探索 save-markdown
的实现思路。首先,我需要根据页面的 url,去 Obsidian 中创建目录。
首先,Obsidian 中有一个 base 目录,比如 999.沧海拾珍自动化
。
在该目录下,按照域名(去掉 www.
前缀)创建目录。如果目录已存在,则不要重复创建。输入是 QUrl 的 URL 地址,返回一个 Python pathlib 的目录,共我后续基于这个目录派生出各个文件。
保存网页中所有图片
这里来了一个棘手的问题,网页正文中的图片,我希望离线缓存到笔记目录当中,做到彻底离线化。
怎么实现呢?Qt 并没有提供 API,从网页中 get 图片(如果有请告诉我!)。一种方法是通过 requsts 再请求一次图片,但我不希望这样。
为了解决这个问题,我给 qutebrowser 加了一层 mitmproxy,具体方法参见《浏览器功能定制3:使用 mitmproxy 增强浏览器的拦截能力》。
总体来说,所有请求中的图片,都将被缓存到一个 Python 字典中。这样,在我离线保存网页的时候,只需要向这个字典中进行查询即可。
小插曲:多进程问题:遇到了一个新问题,mitmproxy 运行在单独进程里,图片缓存字典,在主进程里获取不到。解决方案:将 mitmproxy 从多进程改为多线程,图片缓存可以在跨线程间共享。
HTML 转 Markdown
Step1:加载站点适配规则
我没有设计什么神奇的通用算法,而是针对不同的站点,预置了一些适配规则。
适配规则包括:
- 模拟浏览器操作:自动加载更多
- 图片缓存:确保懒加载的图片都已加载完成
- 样式简化处理:去掉不需要的页面样式,对一些复杂结构进行简化处理
有的甚至可以生成新的网页模板,把内容抠出来,放到新网页模板中去。
基于浏览器的底层 API,不论是模拟操作,还是元素操作,都开启上帝视角,随心所欲。
提取网页正文
实际操作,发现网站众多,光靠匹配还不够。
给出一个文章页,如何识别出最核心的那个 div tag 呢?
Step2:获取渲染后的 HTML
获取渲染后的 HTML,这时 HTML 已经是 ready for markdown 的了。
如果还需要 Hack,适配规则在这里还有一个 hook 时机。
Step3:Html2Markdown
调用 python-markdownify,使用定制的转换器,执行一些更加完美的处理。
如果还需要 Hack,适配规则在这里还有一个 hook 时机。
Step4:拷入 Obsidian
我在 Obsidian 设计了一个专门的文件目录布局:
- 归档目录
- 域名
- 《文章》.md
- 《文章》归档.md
- 《文章》images/
- 域名
其中:
《文章》.md
:是一个元信息书签,包括基本内容,我的总结,用于发布数字花园《文章》归档.md
:存储网页归档内容《文章》images/
:存储图片,并在归档文件中相对路径引用
这样,后续如果要移动目录,只需要三个文件一起移动即可。并且由于名称开头相同,他们在文件管理器中也可以一起出现。
Step5:Schema 自动 Obsidian 跳转
保存完成后,触发 Obsidian 自动打开笔记。在笔记中进行阅读、学习。
这个功能叫 Obsidian URL(Obsidian 链接),格式:obsidian://open?省略
。
只要拼凑出这个链接,通过 Python 触发就可以了。
其它
灵感
在网页正文提取这个主题上,先用已有的库,实现足够多的 html -> Markdown 之后,作为训练集训练一个 LLM。
DEBUG 选项
预留一个 Debug 开关,当开启时,将每一步的中间结果进行保存,方便开一个编辑器,进行调试、检查。
网络资源
本文作者:Maeiee
本文链接:浏览器功能定制1:将网页内容保存为 Markdown
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!